#ifndef __PANEL_DEMO_H__
#define __PANEL_DEMO_H__

#include <wx/wx.h>
#include <wx/aui/aui.h>
#include <wx/wrapsizer.h>
#include <iostream>
#include <streambuf>

// 自定义的streambuf派生类，将输出发送到wxTextCtrl
class TextCtrlOutputStream : public std::streambuf {
public:
    TextCtrlOutputStream(wxListBox* textCtrl) : m_textCtrl(textCtrl) {}

protected:
    virtual int_type overflow(int_type c) {
        if (c != EOF) {
            // 将字符发送到wxTextCtrl
//            m_textCtrl->WriteText(wxString(static_cast<wxChar>(c)));
            // m_textCtrl->WriteText(wxString((char)(c)));
            // m_textCtrl->ShowPosition(m_textCtrl->GetLastPosition());
            m_textCtrl->Append(wxString((char)(c)));
            m_textCtrl->EnsureVisible(m_textCtrl->GetCount() - 1);
        }
        return c;
    }

    virtual std::streamsize xsputn(const char* s, std::streamsize n) {
        // 将字符串发送到wxTextCtrl
        // m_textCtrl->WriteText(wxString(s, n));
        // m_textCtrl->ShowPosition(m_textCtrl->GetLastPosition());
        m_textCtrl->Append(wxString(wxString(s, n)));
        m_textCtrl->EnsureVisible(m_textCtrl->GetCount() - 1);
        return n;
    }

    // int sync() override {
    //     m_textCtrl->AppendText("\n");
    //     return 0;
    // }

private:
    wxListBox* m_textCtrl;
};

// class TextCtrlOutputLog : public wxLog {
// public:
//     TextCtrlOutputLog(wxTextCtrl* textCtrl) : m_textCtrl(textCtrl) {}

// protected:
//     virtual void DoLogText(const wxString& msg) override {
//         if (m_textCtrl) {
//             wxTextCtrl* textCtrl = m_textCtrl;
//             wxCommandEvent event(wxEVT_THREAD, wxID_ANY);
//             event.SetString(msg);
//             wxQueueEvent(textCtrl->GetEventHandler(), event.Clone());
//         }
//     }

// private:
//     wxTextCtrl* m_textCtrl;
// };

class LboxLogger : public wxLog
{
public:
    LboxLogger(wxListBox *lbox, wxLog *logOld)
    {
        m_lbox = lbox;
        //m_lbox->Disable(); -- looks ugly under MSW
        m_logOld = logOld;
    }

    virtual ~LboxLogger()
    {
        wxLog::SetActiveTarget(m_logOld);
    }

private:
    // implement sink functions
    virtual void DoLogTextAtLevel(wxLogLevel level, const wxString& msg) wxOVERRIDE
    {
        if ( level == wxLOG_Trace )
        {
            if ( m_logOld )
                m_logOld->LogTextAtLevel(level, msg);
            return;
        }

        #ifdef __WXUNIVERSAL__
            m_lbox->AppendAndEnsureVisible(msg);
        #else // other ports don't have this method yet
            // m_lbox->Append(msg);
            // m_lbox->SetFirstItem(m_lbox->GetCount() - 1);
            // m_lbox->WriteText(msg);
            // // m_lbox->ShowPosition(m_lbox->GetLastPosition());
            // m_lbox->SetInsertionPointEnd();
            m_lbox->Append(msg);
            m_lbox->EnsureVisible(m_lbox->GetCount() - 1);
        #endif
    }

    // the control we use
    wxListBox *m_lbox;

    // the old log target
    wxLog *m_logOld;
};

class PanelLogger : public wxPanel
{
public:
    PanelLogger(const wxString &title, wxWindowID id = wxID_ANY, wxWindow *parent = nullptr);
    ~PanelLogger();
    typedef enum{
        Log,
        Warning,
        Error
    }LoggerType;

private:
    wxWrapSizer *wrap_layout;
    wxBoxSizer *layout;
    wxAuiPaneInfo paneInfo;
    // wxTextCtrl *text_log;
    wxListBox *text_log;
    wxButton *btn_clear;
    wxTextAttr logTextStyle;
    TextCtrlOutputStream *textOutputStream;
    LboxLogger *textOutputLog;

public:
    wxAuiPaneInfo &GetPaneInfo();
    void SetShow(bool show);
    void AppendLog(LoggerType type,const wxString &str);
    wxListBox *GetTextCtrl();

private:
    void OnButtonClear(wxCommandEvent& event);
};


#endif
